import android.os.Build
import androidx.annotation.RequiresApi
import java.io.File
import java.math.BigDecimal
import java.nio.file.Files
import java.nio.file.Paths

/**
 * 习惯用法 https://book.kotlincn.net/text/idioms.html
 */

/**
 * 函数的默认参数
 */
fun foo(a: Int = 0, b: String = "") {  }


/**
 * 过滤 list
 * 了解 Java 与 Kotlin 过滤的区别。https://book.kotlincn.net/text/java-to-kotlin-collections-guide.html#过滤元素
 */
fun main21() {
    val list = arrayOf(1, 2, 3, 4, 5)
    val positives = list.filter { x -> x > 3 }
    positives.forEach { println(it) }

    //或者可以更短:
    val positives1 = list.filter { it > 2 }
}


/**
 * 检测元素是否存在于集合中
 */
fun main22() {
    val emailsList = arrayOf(1, 2, 3, 4, 5)
    if (1 in emailsList) { println(true) }

    if (2 !in emailsList) { println(false) }
}


/**
 * 字符串内插
 */
fun main23() {
    val name = "张帅"
    println("Name $name")
}


/**
 * 类型判断
 */
fun main24() {
    val x = 1L
    judge(x)
}
fun judge(x: Any) {
    when (x) {
    is Int -> println("$x is Int")
    is Long -> println("$x is Long")
    else   -> println("$x is Unknown")
    }
}


/**
 * 只读 list, map
 */
fun main25() {
    val list = listOf("a", "b", "c")
    val map = mapOf("a" to 1, "b" to 2, "c" to "Hello")
}


/**
 * 访问 map 条目
 */
fun main26() {
    val map = mutableMapOf("a" to 1, "b" to 2, "c" to 3)

    //1.访问 map 条目
    println("a = ${map["a"]}")
    map["a"] = 2

    //2.遍历 map 或者 pair 型 list
    for ((k, v) in map) {               //k 与 v 可以是任何适宜的名称，例如 name 与 age。
        println("$k = $v")
    }
    for (entry in map.entries) {        //map.entries.for
        println(entry)
    }
}


/**
 * 区间迭代
 */
fun main27() {
    for (i in 1..10) {         //闭区间  ：[1, 10]
        print("$i ")
    }
    println()
    for (i in 1 until 10) {    //半开区间：[1, 10)
        print("$i ")
    }
    println()
    for (x in 2..10 step 2) {   //2 4 6 8 10
        print("$x ")
    }
    println()
    for (x in 10 downTo 1) {    //闭区间  ：[10, 1]
        print("$x ")
    }
    println()
    (1..10).forEach {           //闭区间  ：[1, 10]
        print("$it ")
    }
}


/**
 * 延迟属性 lazy
 */
fun main28() {
    val str: String by lazy {   // 该值仅在首次访问时计算, ': String'可省略
        "Test".toUpperCase()
    }
    println(str)                //TEST

    val str2 by lazy {
        "Test2"
    }
}


/**
 * 扩展函数: 给对象增加方法: Object.Xxx() : Yyy {}
 */
fun String.appendLength() : String {
    return "$this: $length"
}
fun main29() {
    val str = "Convert this to camelcase".appendLength()
    println(str)
}


/**
 * 创建单例: object Xxx {}
 */
fun main210() {
    val name = Resource.name    //Resource.INSTANCE.name
}
object Resource {               //public final class Resource
    val name = "Name"
}


/**
 * 实例化一个抽象类  val imp = object : MyAbstractClass() {}
 */
fun main211() {
    abstract class MyAbstractClass {
        open fun doSomething() {        //方法默认是'final', 要加上'open'才能重写方法
            println("do 1")
        }
        abstract fun sleep()
    }

    //1.myObject = new MyAbstractClass(), 匿名内部类对象
    val myObject = object : MyAbstractClass() {
        override fun doSomething() {
            println("do 2")
        }
        override fun sleep() {
            println("Sleep")
        }
    }
    myObject.doSomething()
    myObject.sleep()
}


/**
 * if-not-null 缩写
 */
fun main212() {
    val files = File("C:\\").listFiles()
    println(files?.size)            // 如果 files 不是 null，那么输出其大小（size）
    if (files != null) {
        for (file in files) {
            println(file?.absolutePath)
        }
    }
}


/**
 * if-not-null-else 缩写
 */
fun main213() {
    val files = File("G:\\").listFiles()
    println(files?.size ?: "empty")             // 如果 files 为 null，那么输出“empty”

    // To calculate the fallback value in a code block, use `run`
    val filesSize = files?.size ?: run {
//        return someSize
    }
    println(filesSize)
}


/**
 * if null 执行一个语句
 */
fun main214() {
    val map = mapOf("a" to 1, "b" to 2, "c" to 3)
    val email = map["email"] ?: throw IllegalStateException("Email is missing!")
}


/**
 * 在可能会空的集合中取第一元素
 */
fun main215() {
    val list = listOf("a", "b", "c")
    val email = list.firstOrNull() ?: ""
    println(email)
}


/**
 * if not null 执行代码
 */
fun main216() {
    val value = ""

    value?.let {                // 如果非空(!=null)会执行这个代码块
        println("value = $it")
    }
}


/**
 * 映射可空值（如果非空的话）
 */
fun main217() {
    val value = "Test!"

    // 如果该值或其转换结果为空，那么返回 defaultValue。
    val mapped1 = value?.let { it.appendLength() } ?: "is null"
    val mapped2 = value?.let { null } ?: "is null"
    println("mapped1 = $mapped1, mapped2 = $mapped2")
}


/**
 * 返回 when 表达式
 */
fun main218() {
    fun transform(color: String): Int {
        return when (color) {
            "Red" -> 0
            "Green" -> 1
            "Blue" -> 2
            else -> throw IllegalArgumentException("Invalid color param value")
        }
    }
    val color = transform("Red")
    println("color = $color")
}


/**
 * try-catch 表达式
 */
fun main219() {
    val result = try {
        9 / 3
    } catch (e: ArithmeticException) {
        throw IllegalStateException(e)
    }
    println("result = $result")
}


/**
 * if 表达式
 */
fun main220() {
    val x = 3
    val y = if (x == 1) {
        "one"
    } else if (x == 2) {
        "two"
    } else {
        "other"
    }
    println("x = $x, y = $y")
}


/**
 * 返回类型为 Unit 的方法的构建器风格用法
 */
fun main221() {
    fun arrayOfMinusOnes(size: Int): IntArray {
        return IntArray(size).apply { fill(-1) }
    }

    val minusOnes = arrayOfMinusOnes(5)
    for (minusOne in minusOnes) {
        print("$minusOne ")                 //-1 -1 -1 -1 -1
    }
}


/**
 * 单表达式函数
 */
fun main222() {
    fun theAnswer0() = 32
    //等价于
    fun theAnswer1(): Int {
        return 42
    }

    //单表达式函数与其它惯用法一起使用能简化代码，例如和 when 表达式一起使用：
    fun transform(color: String): Int = when (color) {
        "Red" -> 0
        "Green" -> 1
        "Blue" -> 2
        else -> throw IllegalArgumentException("Invalid color param value")
    }
}


/**
 * 对一个对象实例调用多个方法 （with）
 */
fun main223() {
    class Turtle {                      //乌龟; 海龟; 鳖; (任何种类的)龟; 陆龟; 水龟;
        fun penDown() {}
        fun penUp() {}
        fun turn(degrees: Double) {}
        fun forward(pixels: Double) {}
    }

    val myTurtle = Turtle()
    with(myTurtle) {                    // 画一个 100 像素的正方形
        penDown()
        for (i in 1..4) {
            forward(100.0)
            turn(90.0)
        }
        penUp()
    }
}


/**
 * 配置对象的属性（apply）
 */
fun main224() {
    class Rectangle {
        var length: Int = 0
    }
    val myRectangle = Rectangle().apply {
        length = 4
    }
    println(myRectangle.length)
}


/**
 * Java 7 的 try-with-resources
 */
@RequiresApi(Build.VERSION_CODES.O)
fun main225() {
    val stream = Files.newInputStream(Paths.get("G:\\demo.log"))
    stream.buffered().reader().use { reader ->
        println(reader.readText())
    }
}


/**
 * 需要泛型信息的泛型函数
 * inline: a.内联的, 一列式；排成行的；串联式的；联机的；轴向式的；在（一直）线上的;
 * reified: a.具体化的
 */
//public final class Gson {
//    public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
//Kotlin 写法
//inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json, T::class.java)


/**
 * 可空布尔
 */
fun main226() {
    val b: Boolean? = null
    if (b == true) {
        println("'b' = true")
    } else {
        println("`b` 是 false 或者 null")
    }
}


/**
 * 交换两个变量
 */
fun main227() {
    var a = 1
    var b = 2
    a = b.also { b = a }
    println("a = $a, b = $b")
}


/**
 * 将代码标记为不完整（TODO）
 * Kotlin 的标准库有一个 TODO() 函数，该函数总是抛出一个 NotImplementedError。
 *     其返回类型为 Nothing，因此无论预期类型是什么都可以使用它。 还有一个接受原因参数的重载：
 */
fun main228() {
    fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")
    val bigDecimal = calcTaxes()
    println(bigDecimal)
}

